package com.example.learningnote.basic;

// Java中所有的类都是继承 Object
// 常用方法
// - toString()  返回对象的字符串表示
// -  equals()   比较两个对象是否相等 内存地址
// - hashCode()  返回对象的哈希码，通常用于哈希表（如 HashMap）
// abstract 代表抽象类  场景是父类定义一个方法壳 具体实现都在子类中时 那么实例化父类也就没有意义
public abstract class Person {
    // 属性 实例化时都会有一个默认值 String类型是null  int类型是0
    String name;
    static int age; // static 静态成员、类成员 意思是无论实例化多少个对象 最后都会共用这一个static 修饰的属性 类对象共享
    private String sex ; // 私有属性 外部不可访问

    // 构造方法  只能在对象实例化时调用
    // 若类中没有声明 那么类在实例化时会自动执行一个无参的构造方法
    Person(String name, int age , String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public static int getAge() {
        return age;
    }

    public static void setAge(int age) {
        Person.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    // 方法  类的实例方法  必须通过实例化对象调用
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "', sex=" + sex + '}';
    }
    // 类方法 静态方法  不需要通过实例化也可以调用
    public static String play(String name){
        // 静态方法中不能直接访问非静态成员
        return name + "开始玩游戏";
    }

    public String eat(){
        return this.getName() + "在吃东西";
    }

    // final 修饰方法 不能被子类继承
    // final 修饰变量 使变量的值不可更改（常量），一旦赋值，值不能再变；引用不可变（但对象内容可能可变）
    // final 修饰类 防止类被继承；
    final String dance (){
        return this.getName() + "在跳舞";
    }

    // 抽象方法  不允许有方法体  子类 必须要重写这个方法
    public abstract void speak();
}

/*
1. final
作用：表示“不可变”或“最终”，用于限制修改。
使用场景：
修饰变量：使变量的值不可更改（常量）。一旦赋值，值不能再变。
final int MAX_AGE = 100; // 常量，值不可修改
对于基本类型，值不可变；对于引用类型，引用不可变（但对象内容可能可变）。
final StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 合法，对象内容可变
// sb = new StringBuilder("New"); // 非法，引用不可变
修饰方法：防止子类重写（override）该方法。
class Parent {
    final void doSomething() {
        System.out.println("Cannot override");
    }
}
修饰类：防止类被继承。
final class MyClass {
    // 不可被继承
}
特点：提高代码安全性和可预测性，常用于定义常量或保护关键逻辑。
2. static
作用：表示“静态”或“类级别”，与类绑定，而不是与对象实例绑定。
使用场景：
修饰变量：创建类级别的共享变量，所有对象共享同一份数据。
class Person {
    static int count = 0; // 所有对象共享
    Person() {
        count++;
    }
}
修饰方法：定义类方法，无需实例化即可调用。
class MathUtils {
    static int add(int a, int b) {
        return a + b;
    }
}
// 调用：MathUtils.add(2, 3);
修饰代码块：静态初始化块，在类加载时执行一次。
static {
    System.out.println("Class loaded");
}
修饰内部类：使内部类不依赖外部类实例。
特点：
静态成员在类加载时初始化，存在于整个程序生命周期。
静态方法不能直接访问非静态成员（因为没有对象实例）。
常用于工具类（如 Math）或共享资源。
3. public
作用：表示“公开”，允许无限制访问。
使用场景：
修饰类、方法、变量：使它们可以被任何地方的代码访问。
public class MyClass {
    public int value = 10;
    public void sayHello() {
        System.out.println("Hello");
    }
}
其他包中的类可以访问：
MyClass obj = new MyClass();
System.out.println(obj.value); // 合法
obj.sayHello(); // 合法
特点：
提供最大访问权限，适合定义对外暴露的接口或 API。
需要谨慎使用，避免暴露过多内部实现。
4. private
作用：表示“私有”，限制访问，仅允许在定义它的类内部使用。
使用场景：
修饰方法、变量：隐藏实现细节，防止外部直接访问。
class Person {
    private String name = "Alice";
    private void secret() {
        System.out.println("Secret");
    }
    public String getName() {
        return name; // 通过公共方法访问
    }
}
外部无法直接访问：
Person p = new Person();
// System.out.println(p.name); // 非法
// p.secret(); // 非法
System.out.println(p.getName()); // 合法
修饰构造函数：限制对象创建（如单例模式）。
class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}
特点：
增强封装性，保护数据安全。
常与 getter/setter 结合，提供受控访问。
区别总结
关键字	作用	适用对象	访问性/约束性
final	不可变/最终	类、方法、变量	限制修改或继承
static	类级别/静态	变量、方法、代码块、内部类	与类绑定，共享或无需实例调用
public	公开访问	类、方法、变量、构造函数	允许任何地方访问
private	私有访问	方法、变量、构造函数	仅类内部访问，隐藏实现
组合使用
这些关键字可以组合使用，但有一定规则：

final 和 static：常用于定义常量。
public static final int MAX_VALUE = 100;
public 和 static：定义公开的类方法。
public static void main(String[] args) {}
private 和 final：定义不可变的私有字段。
private final String id = "123";
注意：static 方法不能被 final 修饰的类中的方法重写（因为 static 方法属于类），但可以被隐藏。
* */

